module dwt.ole.win32.olemisc;

private import dwt.dwt;
private import dwt.internal.ole.win32.com;
private import dwt.ole.win32.ole;
private import dwt.ole.win32.olecontrolsite;
private import dwt.util.util;
private import dwt.util.vector;
private import dwt.util.eventhandler;
private import dwt.widgets.widget;
private import dwt.ole.win32.variant;


public class OleEvent {
	public int type;
	public Widget widget;
	public int detail;
	public boolean doit = true;
	public Variant[] arguments;

	// customized data
	public Object cData;
	// public Object[] cDatas;
}


/**
* The OleEventTable class implements a simple
* look up mechanism that maps an event type
* to a listener.  Muliple listeners for the
* same event type are supported.
*
*/

/**
 * <Shawn> OleEventTable is modified to support D delegate mechanism
 */
class OleEventTable {
	int [] types;
	OleListener [] listeners;
	
	TypedHandler[] handlers;

	
// <Shawn> hook a delegate handler
public void hook (TypedHandler handler) {
	assert(handler);	
	
	if (handler !is null) {
		handlers ~= handler;
	}
}
	
void hook (int eventType, OleListener handler) {
	if (types is null) types = new int [4];
	if (listeners is null) listeners = new OleListener [4];
	for (int i=0; i<types.length; i++) {
		if (types [i] == 0) {
			types [i] = eventType;
			listeners [i] = handler;
			return;
		}
	}
	int size = types.length;
	int [] newTypes = new int [size + 4];
	OleListener [] newHandlers = new OleListener [size + 4];
	System.arraycopy (types, 0, newTypes, 0, size);
	System.arraycopy (cast(Object[])listeners, 0, cast(Object[])newHandlers, 0, size);
	types = newTypes;  
	listeners = newHandlers;
	types [size] = eventType;  
	listeners [size] = handler;
}

boolean hooks (int eventType) {

	for (int i=0; i<types.length; i++) {
		if (types [i] == eventType) return true;
	}
	foreach(TypedHandler hand; handlers){
		if(hand !is null  && hand.eventType == eventType)
			return true;
	}
	return false;
}

void sendEvent (OleEvent event) {
	for (int i=0; i<types.length; i++) {
		if (types [i] == event.type) {
			OleListener listener = listeners [i];
			if (listener !is null) listener.handleEvent (event);
		}
	}
	
	// proc delegates handlers
	foreach(TypedHandler hand; handlers) {
		if(hand !is null && hand.eventType == event.type){
			hand.handleEvent(event);
		}
	}
}

void unhook (int eventType, OleListener handler) {
	for (int i=0; i<types.length; i++) {
		if ((types [i] == eventType) && (listeners [i] is handler)) {
			types [i] = 0;
			listeners [i] = null;
			return;
		}
	}
}

// <Shawn> Unhook a delegate 
public void unhook (TypedHandler handler) {
	if (handlers is null) return;
	for(int i=0; i<handlers.length; ++i) {
		TypedHandler hand = handlers[i];
		if(hand && hand.equals(handler)){
			TVector!(TypedHandler).remove(handlers, hand);
			hand = null;
			return;
		}
	}
}

boolean hasEntries() {
	for (int i=0; i<types.length; i++) {
		if (types[i] != 0) return true;
	}
	foreach(TypedHandler hand; handlers){
		if(hand !is null) 
			return true;
	}
	return false;
}

}	// end of OleEventTable

public class OleFunctionDescription {

	public int id;
	public char[] name;
	public OleParameterDescription[] args;
	public int optionalArgCount;
	public ushort returnType;
	public int invokeKind;
	public int funcKind;
	public ushort flags;
	public int callingConvention;
	public char[] documentation;
	public char[] helpFile;
}	


public interface OleListener
{
	public void handleEvent(OleEvent event);
}

public class OleParameterDescription {
	public char[] name;
	public short flags;
	public short type;
}

public class OlePropertyDescription {
	public int id;
	public char[] name;
	public int type;
	public int flags;
	public int kind;
	public char[] description;
	public char[] helpFile;
}
